package com.gopay.scheduler.job;
 
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.constants.trans.PayBankOpType;
import com.gopay.common.cps.service.autosettle.impl.AutoSettleHelper;
import com.gopay.common.cps.service.cbrmb.CbRmbAutoSettleHelper;
import com.gopay.common.domain.cps.CpsGenMainOrder;
import com.gopay.common.domain.cps.cbrmb.Tran01721PortalVO;
import com.gopay.common.domain.cps.vo.CPSResponse;
import com.gopay.common.util.DateUtils;
import com.gopay.scheduler.GopayBaseJob;
import com.gopay.scheduler.common.CallCPSHelper;
import com.gopay.scheduler.service.cbrmb.CbRmbAutoSettleService;

/**
 * 跨境人民币出口自动结算Job
 * 
 * @CbRmbAutoSettleJob.java
 * @author qianld
 * @2016-07-11  上午11:39:35 www.gopay.com.cn Inc.All rights reserved.
 */
public class CbRmbOutAutoSettleJob extends GopayBaseJob {
    // 日志
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 统计天数，跨境的结算周期有可能是15天，加上最长的节假日7天，天数可以设置为30天
     */
    private static final int STATI_DAYS = 30;

    /**
     * 最近一个月的法定工作日列表
     */
    private List<String> legalWorkList;

    private String startDay;

    private String today;

    @Resource(name = "callCPSHelper")
    private CallCPSHelper callCPSHelper;

    @Resource(name = "cbRmbAutoSettleService")
    private CbRmbAutoSettleService cbRmbAutoSettleService;

    @Resource(name = "autoSettleHelper")
    private AutoSettleHelper autoSettleHelper;

    @Override
    public void doJobInternal() {
        

        // 当前时间
        Date curDate = new Date();
        
        // 初始化数据
        init(curDate);

        if (curDate.getMinutes()/3%2==0) {    
               
            // 执行零点判断
            doZeroJudge();
        } else {
            // 判断今天是否为节假日,这个还是走普通的节假日
            if (autoSettleHelper.isHoliday(curDate)) {
                // 对当天结算的并且结算日为节假日的T+N订单执行十点银企直连
                doTenBCDL();
            }
        }

       
    }

    /**
     * 初始化数据
     * 
     * @param curDate
     */
    protected void init(Date curDate) {
        // 查询最近一个月的法定工作日
        legalWorkList = autoSettleHelper.queryLegalWorkDayOfRecentOneMonth(curDate);

        logger.error("--跨境的legalWorkList=" + legalWorkList.toString());

        // 当前时间
        today = DateUtils.format(curDate, "yyyyMMdd");

        // 计算T-30的日期
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(curDate);
        calendar.add(Calendar.DAY_OF_MONTH, -STATI_DAYS);
        startDay = DateUtils.format(calendar.getTime(), "yyyyMMdd");

        logger.error("--today=" + today + ",startDay=" + startDay);
    }

    /**
     * 执行零点判断
     */
    protected void doZeroJudge() {
        // 查询订单之零点判断
        List<CpsGenMainOrder> mainList = cbRmbAutoSettleService.queryOrderOfJudge(startDay, today);

        logger.error("cbrmb 有这些订单要判断是否今天结算--queryOrder--mainList.size=" + mainList.size());

        // 筛选出结算日为今天的订单
        List<CpsGenMainOrder> orderList = new ArrayList<CpsGenMainOrder>();
        for (CpsGenMainOrder main : mainList) {
            try{
                logger.error("订单要判断是否今天结算------GopayOrderId=" + main.getGopayOrderId());
                if (checkTodayIsSettleDay(main, main.getTransDtlSq(), today, main.getRemark1(), main.getRemark2(),main.getOrderType())) {
                    orderList.add(main);
                }
            } catch (Exception e) {
                // 吃掉所有异常
                logger.error("checkTodayIsSettleDay Error", e);
            }
        }

        logger.error("跨境人民币出口查出要做0点任务的有--queryOrder--orderIdList.size=" + orderList.size());

        // 调用CPS
        Object paramVo;
        CPSResponse response;
        CpsGenMainOrder main;
        for (int i = 0; i < orderList.size(); i++) {
            main = orderList.get(i);

            // 封装cps请求参数vo
            paramVo = buildCallCpsParamVo(main, true);

            logger.error("doZeroJudge------GopayOrderId=" + main.getGopayOrderId());
            try {
                // 调用cps
                response = callCPSHelper.callCbRmbByVOTicket(paramVo);
                if (!ProcCodeConstants.PROC_CODE_100S1000.equals(response.getRespCode())) {
                    logger.error("------调用cps返回异常  response=" + response.getRespCode());
                }
            } catch (Exception e) {
                // 吃掉所有异常
                logger.error("callByVOTicket Error", e);
            }
        }

    }

    /**
     * 校验今天是否为结算日
     * 
     * @param main
     * @param settleCircle
     * @return
     */
    private boolean checkTodayIsSettleDay(CpsGenMainOrder main, int settleCircle, String today, String cardNum,
            String bankName,String bcFlag) {
        //获取银行Code
        String bankCode=autoSettleHelper.queryPayBankCode(main,bankName,bcFlag,cardNum);
        
        //客户Id
        String payCustId=main.getPayCustId();
        
        // 根据客户节假日白名单规则查询额外工作日
        List<String> extraWorkList = autoSettleHelper.queryExtraWorkDayByCustHolidayRule(payCustId, cardNum,
                bankCode, DateUtils.format(main.getGopayTxnTm(), "yyyyMMdd"), today,main.getGopayIntTxnCd());
           logger.info(payCustId+"节假日白名单:"+extraWorkList.toString());
        String ruleId = null;

        // 计算结算日
        String settleDay = "";
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(main.getGopayTxnTm());//这个其实就是审核的时间，在processApplyReConfirm已经模拟了2天
        int count = 0;
        for (int i = 1; i <= STATI_DAYS; i++) {
            calendar.add(Calendar.DAY_OF_MONTH, 1);
            String tmpDay = DateUtils.format(calendar.getTime(), "yyyyMMdd");

            if (legalWorkList.contains(tmpDay)) {
                ruleId=null;
                count++;
            } else {
                for (String extra : extraWorkList) {
                    if (extra.startsWith(tmpDay)) {
                        ruleId = extra.substring(9);
                        count++;
                        break;
                    }
                }
            }
            if (count >= settleCircle) {
                settleDay = tmpDay;
                break;
            }
        }

        // 借用属性返回ruleId
        main.setRemark1(ruleId);

        return today.equals(settleDay);
    }

    /**
     * 封装cps请求参数vo
     * 
     * @param gopayOrderId
     * @param intTxnCd
     * @return
     */
    private Object buildCallCpsParamVo(CpsGenMainOrder main, boolean isZeroJudge) {
        String gopayOrderId = main.getGopayOrderId();
        String ruleId = main.getRemark1();

        Object obj = null;
       
            Tran01721PortalVO paramVo = new Tran01721PortalVO();
            paramVo.setGopayOrderId(gopayOrderId);
            paramVo.setOpType(isZeroJudge ? PayBankOpType.AUTO_SETTLE_JOB_JUDGE : PayBankOpType.AUTO_SETTLE_JOB_BCDL);
            paramVo.setRuleId(isZeroJudge ? ruleId : null);

            obj = paramVo;
       

        return obj;
    }

    /**
     * 对结算日为节假日的T+N订单执行十点银企直连
     */
    protected void doTenBCDL() {
        // 查询订单之十点银企直连
        List<CpsGenMainOrder> orderList = cbRmbAutoSettleService.queryOrderOfBCDL(startDay, today);

        logger.error("跨境的doTenBCDL--queryOrder--orderList.size=" + orderList.size());


        // 调用CPS
        Object paramVo;
        CPSResponse response;
        CpsGenMainOrder main;
        for (int i = 0; i < orderList.size(); i++) {
            main = orderList.get(i);

            // 封装cps请求参数vo
            paramVo = buildCallCpsParamVo(main, false);

            logger.error("doTenBCDL------GopayOrderId=" + main.getGopayOrderId());
            try {
                // 调用cps
                response = callCPSHelper.callCbRmbByVOTicket(paramVo);
                if (!ProcCodeConstants.PROC_CODE_100S1000.equals(response.getRespCode())) {
                    logger.error("------调用cps返回异常  response=" + response.getRespCode());
                }
            } catch (Exception e) {
                // 吃掉所有异常
                logger.error("callByVOTicket Error", e);
            }
        }
    }

}
